package cn.itcast.dewu.service.impl;

import cn.hutool.core.lang.UUID;
import cn.itcast.dewu.dto.Result;
import cn.itcast.dewu.dto.FollowType;
import cn.itcast.dewu.utils.RedisIdWork;
import cn.itcast.dewu.utils.UserHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.itcast.dewu.pojo.Follow;
import cn.itcast.dewu.service.FollowService;
import cn.itcast.dewu.mapper.FollowMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

/**
* @author Administrator
* @description 针对表【tb_follow】的数据库操作Service实现
* @createDate 2022-04-29 14:06:30
*/
@Service
@Slf4j
public class FollowServiceImpl extends ServiceImpl<FollowMapper, Follow>
    implements FollowService{
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedisIdWork idWork;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public Result follow(Long followUserId, Boolean isFollow) {
        //获取当前的用户
        Long userId = UserHolder.getUser().getId();
        Follow follow = new Follow();
        if (isFollow) {
            //关注
            follow.setUserId(userId);
            follow.setId(idWork.nextID("follow:user:"));
            follow.setFollowUserId(followUserId);
            boolean falg = save(follow);

            if (falg){
                rabbitMessage(followUserId, userId,isFollow);
                    // 把关注用户的id，放入redis的set集合 sadd userId followerUserId
                    stringRedisTemplate.opsForSet().add("follow:"+userId, followUserId.toString());

            }


        }else {
            //取消关注
            LambdaQueryWrapper<Follow> queryWrapper = new LambdaQueryWrapper();
            queryWrapper.eq(Follow::getUserId, userId).eq(Follow::getFollowUserId, followUserId);
            boolean falg = remove(queryWrapper);
            if (falg){
                rabbitMessage(followUserId, userId,isFollow);
                stringRedisTemplate.opsForSet().add("follow:"+userId, followUserId.toString());
            }

        }

        return Result.ok();
    }
    /*
    * 异步处理关注 取消关注
    * */
    private void rabbitMessage(Long followUserId, Long userId,Boolean isFollow) {
        FollowType followType = new FollowType();
        followType.setFollowUserId(followUserId).setIsFollow(isFollow).setUserId(userId);

        String id = followUserId + "," + userId;
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString(true));
        correlationData.getFuture().addCallback(
                result2 -> {
                    if (result2.isAck()) {
                        log.info("消息发送成功,消息id为:{}",correlationData.getId());
                    }else{
                        log.error("消息发送到交换机失败,消息的id为:{},发送失败的原因为:{}"
                                ,correlationData.getId(),result2.getReason());
                        //重新发送消息
                        rabbitTemplate.convertAndSend("userinfo.follow.exchange",
                                "userinfo.follow",followType,correlationData);
                    }
                },
                ex->{
                    log.error("消息发送异常,消息的id为:{},发送失败的原因为:{}"
                            ,correlationData.getId(),ex.getMessage());
                    //重新发送消息
                    rabbitTemplate.convertAndSend("userinfo.follow.exchange",
                            "userinfo.follow",followType,correlationData);
                }
        );
        //发送消息
        rabbitTemplate.convertAndSend("userinfo.follow.exchange",
                "userinfo.follow",followType,correlationData);
    }

    /*
    * */
    @Override
    public Result isFollow(Long followUserId) {
        Long userId = UserHolder.getUser().getId();

        Integer count = query().eq("user_id", userId).eq("follow_user_id", followUserId).count();
        return Result.ok(count > 0);
    }
}




